home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / CHESS.PAK / EVALU.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  18KB  |  480 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1991, 1993 by Borland International
  3. //----------------------------------------------------------------------------
  4. #include <owl/pch.h>
  5. #include <owl/defs.h>
  6. #include <math.h>
  7. #include "wcdefs.h"
  8. #include "externs.h"
  9.  
  10. MAXTYPE RootValue;
  11. BOARDTYPE Board[0x78];
  12.  
  13. #undef max
  14. #undef min
  15. #define max(a, b)  (((a) > (b)) ? (a) : (b))
  16. #define min(a, b)  (((a) < (b)) ? (a) : (b))
  17.  
  18. #define    TOLERANCE        8  //  Tolerance width
  19. #define    EXCHANGEVALUE    32
  20.     //  Value for exchanging pieces when ahead (not pawns)
  21. #define    ISOLATEDPAWN     20
  22.    //  Isolated pawn.  Double isolated pawn is 3 * 20
  23. #define    DOUBLEPAWN       8  //  Double pawn
  24. #define    SIDEPAWN        6  //  Having a pawn on the side
  25. #define    CHAINPAWN        3  //  Being covered by a pawn
  26. #define    COVERPAWN        3  //  covering a pawn
  27. #define    NOTMOVEPAWN      2  //  Penalty for moving pawn
  28. #define    BISHOPBLOCKVALUE  20
  29.    //  Penalty for bishop blocking d2/e2 pawn
  30. #define    ROOKBEHINDPASSPAWN 16  //  Bonus for Rook behind passed pawn
  31.  
  32.  
  33. typedef unsigned char FILETYPE;  //  file numbers
  34. typedef unsigned char RANKTYPE;  //  rank numbers
  35. typedef unsigned char SETOFFILE;
  36. typedef struct {
  37.   SETOFFILE one, dob;
  38. } PAWNBITTYPE[2];
  39.  
  40. //
  41. //  Global variables for this module
  42. //
  43. int PieceValue[7] = {0, 0x1000, 0x900, 0x4c0, 0x300, 0x300, 0x100};
  44. const char distan[8] = { 3, 2, 1, 0, 0, 1, 2, 3 };
  45.    //  The value of a pawn is the sum of Rank and file values.
  46.    //   The file value is equal to PawnFileFactor * (Rank Number + 2)
  47. const char pawnrank[8] = {0, 0, 0, 2, 4, 8, 30, 0};
  48. const char passpawnrank[8] = {0, 0, 10, 20, 40, 60, 70, 0};
  49. const char pawnfilefactor[8] = {0, 0, 2, 5, 6, 2, 0, 0};
  50. const char castvalue[2] = {4, 32};  //  Value of castling
  51.  
  52. const SETOFFILE filebittab[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
  53. PAWNBITTYPE pawnbitt[MAXPLY + 2];
  54. PAWNBITTYPE *pawnbit = &pawnbitt[1];
  55. int totalmaterial, pawntotalmaterial, material;
  56.   //  Material level of the game
  57.   //    (early middlegame = 43 - 32, endgame = 0)
  58. int materiallevel;
  59. const unsigned char squarerankvalue[8] = { 0, 0, 0, 0, 1, 2, 4, 4};
  60. COLORTYPE tempcolor;
  61. int temp, temp2;  //  temporary junk
  62.  
  63.  
  64. //
  65. //  count the number of set bits in b
  66. //
  67. static int
  68. count(SETOFFILE b)
  69. {
  70.   char cnt = 0;
  71.   while (b) {
  72.     if (b % 2 == 1)
  73.       cnt++;
  74.     b >>= 1;
  75.   }
  76.   return cnt;
  77. }
  78.  
  79. //
  80. //  Calculate value of the pawn structure in pawnbit[depth][color]
  81. //
  82. static int
  83. pawnstrval(DEPTHTYPE depth, COLORTYPE color)
  84. {
  85.   SETOFFILE iso;  //  contains FILEs with isolated pawns
  86.  
  87.   iso = SETOFFILE(pawnbit[depth][color].one &
  88.     ~((pawnbit[depth][color].one << 1) | (pawnbit[depth][color].one >> 1)));
  89.   return -(count(pawnbit[depth][color].dob) * DOUBLEPAWN +
  90.       count(iso) * ISOLATEDPAWN + count(iso &
  91.         pawnbit[depth][color].dob) * ISOLATEDPAWN * 2);
  92. }
  93.  
  94. //
  95. //  calculate the value of the piece on the square
  96. //
  97. inline int
  98. PiecePosVal(PIECETYPE piece, COLORTYPE color, SQUARETYPE square)
  99. {
  100.   return PieceValue[piece] + PVTable[color][piece][square];
  101. }
  102.  
  103.  
  104. short mating;  //  mating evaluation function is used
  105.  
  106. //
  107. //  calculates piece-value table for the static evaluation function
  108. //
  109. void
  110. CalcPVTable()
  111. {
  112.   typedef SETOFFILE PAWNTABTYPE[8];
  113.  
  114.   PAWNTABTYPE pawntab[2];
  115.   //  Bit tables for static pawn structure evaluation
  116.   SETOFFILE pawnfiletab, bit, oppasstab, behindoppass,
  117.     leftsidetab, rightsidetab, sidetab, leftchaintab,
  118.     rightchaintab, chaintab, leftcovertab, rightcovertab;
  119.  
  120.   //  Importance of an attack of the square
  121.   char attackvalue[2][0x78];
  122.   //  Value of squares controlled from the square
  123.   int pvcontrol[2][5][0x78];
  124.  
  125.   COLORTYPE losingcolor;   //  the color which is being mated
  126.   int posval;              //  The positional value of piece
  127.   int attval;              //  The attack value of the square
  128.   FILETYPE line;           //  The file of the piece
  129.   RANKTYPE rank;           //  The rank of the piece
  130.   char dist, kingdist;     //  Distance to center, to opponents king
  131.   CASTTYPE cast;           //  Possible castlings
  132.   short direct;            //  Indicates direct attack
  133.   int cnt;                 //  Counter for attack values
  134.   int strval;              //  Pawnstructure value
  135.   COLORTYPE color, oppcolor; //  Color and opponents color
  136.   PIECETYPE piececount;    //  Piece counter
  137.   SQUARETYPE square;       //  Square counter
  138.   DIRTYPE dir;             //  Direction counter
  139.   EDGESQUARETYPE sq;       //  Square counter
  140.   int temp, temp2;         //  temporary junk
  141.  
  142.   //  Calculate SAMMAT, PAWNSAMMAT and Material
  143.   material = pawntotalmaterial = totalmaterial = mating = 0;
  144.  
  145.   for (square = 0; square < 0x78; square++)
  146.     if (!(square & 0x88))
  147.       if (Board[square].piece != empty)
  148.         if (Board[square].piece != king) {
  149.           temp = PieceValue[Board[square].piece];
  150.           totalmaterial += temp;
  151.           if (Board[square].piece == pawn)
  152.             pawntotalmaterial += PieceValue[pawn];
  153.           if (Board[square].color == white)
  154.             temp = -temp;
  155.           material -= temp;
  156.         }
  157.   materiallevel = max(0, totalmaterial - 0x2000) / 0x100;
  158.   //  Set mating if weakest player has less than the equivalence
  159.   //  of two bishops and the advantage is at least a rook for a bishop
  160.   if (material < 0)
  161.     losingcolor = white;
  162.   else
  163.     losingcolor = black;
  164.   mating = ((totalmaterial - abs(material)) / 2 <= PieceValue[bishop] * 2)
  165.     && (abs(material) >= PieceValue[rook] - PieceValue[bishop]);
  166.   //  Calculate ATTACKVAL (importance of each square)
  167.   for (rank = 0; rank < 8; rank++)
  168.     for (line = 0; line < 8; line++) {
  169.       square = (rank << 4) + line;
  170.       attval = max(0, 8 - 3 * (distan[rank] + distan[line]));
  171.           //  center importance
  172.           //  Rank importrance
  173.       for (color = white; color <= black; ((int)color)++) {
  174.         attackvalue[color][square] = char(((squarerankvalue[rank] * 3 *
  175.            (materiallevel + 8)) >> 5) + attval);
  176.         square ^= 0x70;
  177.       }
  178.     }
  179.   for (color = white; color <= black; ((int)color)++) {
  180.     oppcolor = (COLORTYPE)(1 - color);
  181.     CalcCastling(oppcolor, &cast);
  182.     if (cast != shrt && materiallevel > 0)
  183.       //  Importance of the 8 squares around the opponent's King
  184.     for (dir = 0; dir < 8; dir++) {
  185.       sq = PieceTab[oppcolor][0].isquare + DirTab[dir];
  186.       if (!(sq & 0x88))
  187.         attackvalue[color][sq] += char(((12 * (materiallevel + 8)) >> 5));
  188.     }
  189.   }
  190.  
  191.   //  Calculate PVControl
  192.   for (square = 0x77; square >=0; square--)
  193.     if(!(square & 0x88))
  194.       for (color = white; color <= black; ((int)color)++)
  195.         for (piececount = rook; piececount <= bishop; ((int)piececount)++)
  196.           pvcontrol[color][piececount][square] = 0;
  197.   for (square = 0x77; square >=0; square--)
  198.     if (!(square & 0x88))
  199.       for (color = white; color <= black; ((int)color)++) {
  200.         for (dir = 7; dir >= 0; dir--) {
  201.           if (dir < 4)
  202.             piececount = rook;
  203.           else
  204.             piececount = bishop;
  205.           //  Count value of all attacs from the square in
  206.           //  the Direction.
  207.           //  The Value of attacking a Square is Found in ATTACKVAL.
  208.           //  Indirect Attacks (e.g. a Rook attacking through
  209.           //  another Rook) counts for a Normal attack,
  210.           //  Attacks through another Piece counts half
  211.           cnt = 0;
  212.           sq = square;
  213.           direct = 1;
  214.           do {
  215.             sq += DirTab[dir];
  216.             if (sq & 0x88)
  217.               goto TEN;
  218.             temp = attackvalue[color][sq];
  219.             if (direct)
  220.               cnt += temp;
  221.             else
  222.               cnt += (temp >> 1);
  223.             if (Board[sq].piece != empty)
  224.               if (Board[sq].piece != piececount && Board[sq].piece != queen)
  225.                 direct = 0;
  226.           } while (Board[sq].piece != pawn);
  227. TEN:        pvcontrol[color][piececount][square] += (cnt >> 2);
  228.         }
  229.       }
  230.  
  231.   //  Calculate PVTable, value by value
  232.   for (square = 0x77; square >= 0; square--)
  233.     if (!(square & 0x88)) {
  234.       for (color = white; color <= black; ((int)color)++) {
  235.         oppcolor = (COLORTYPE)(1 - color);
  236.         line = FILETYPE(square & 7);
  237.         rank = RANKTYPE(square >> 4);
  238.         if (color == black)
  239.           rank = RANKTYPE(7 - rank);
  240.         dist = char(distan[rank] + distan[line]);
  241.         kingdist = char(abs((square >> 4) - (PieceTab[oppcolor][0].isquare >> 4)) +
  242.                    ((square - PieceTab[oppcolor][0].isquare) & 7));
  243.         for (piececount = king; piececount <= pawn; ((int)piececount)++) {
  244.           posval = 0;    //  Calculate POSITIONAL Value for
  245.                          //  The piece on the Square
  246.           if (mating && piececount != pawn) {
  247.             if (piececount == king)
  248.               if (color == losingcolor) {  //  Mating evaluation
  249.                 posval = 128 - 16 * distan[rank] - 12 * distan[line];
  250.                 if (distan[rank] == 3)
  251.                   posval -= 16;
  252.  
  253.               } else {
  254.                 posval = 128 - 4 * kingdist;
  255.                 if (distan[rank] >= 2 || distan[line] == 3)
  256.                   posval -= 16;
  257.              }
  258.           } else {
  259.             temp = pvcontrol[color][rook][square];
  260.             temp2 = pvcontrol[color][bishop][square];
  261.             //  Normal evaluation function
  262.             switch (piececount) {
  263.               case king:
  264.                 if (materiallevel <= 0)
  265.                   posval = -2 * dist;
  266.                 break;
  267.               case queen:
  268.                 posval = (temp + temp2) >> 2;
  269.                 break;
  270.               case rook:
  271.                 posval = temp;
  272.                 break;
  273.               case bishop:
  274.                 posval = temp2;
  275.                 break;
  276.               case knight:
  277.                 cnt = 0;
  278.                 for (dir = 0; dir < 8; dir++) {
  279.                   sq = square + KnightDir[dir];
  280.                   if (!(sq & 0x88))
  281.                     cnt += attackvalue[color][sq];
  282.                 }
  283.                 posval = (cnt >> 1) - dist * 3;
  284.                 break;
  285.               case pawn :
  286.                 if (rank != 0 && rank != 7)
  287.                   posval = pawnrank[rank] + pawnfilefactor[line] * (rank+2) - 12;
  288.             }
  289.           }
  290.           PVTable[color][piececount][square] = posval;
  291.         }
  292.       }
  293.     }
  294.  
  295.     //  Calculate pawntab (indicates which squares contain pawns)
  296.  
  297.     for (color = white; color <= black; ((int)color)++)
  298.       for (rank = 0; rank < 8; rank++)
  299.         pawntab[color][rank] = 0;
  300.     for (square = 0x77; square >= 0; square--)
  301.       if (!(square & 0x88))
  302.         if (Board[square].piece == pawn) {
  303.           rank = RANKTYPE(square >> 4);
  304.           if (Board[square].color == black)
  305.             rank = RANKTYPE(7 - rank);
  306.           pawntab[Board[square].color][rank] |= filebittab[square & 7];
  307.         }
  308.     for (color = white; color <= black; ((int)color)++) {  //  initialize pawnbit
  309.       pawnbit[-1][color].one = pawnbit[-1][color].dob = 0;
  310.       for (rank = 1; rank < 7; rank++) {
  311.         temp = pawntab[color][rank];
  312.         pawnbit[-1][color].dob |= SETOFFILE((pawnbit[-1][color].one & temp));
  313.         pawnbit[-1][color].one |= SETOFFILE(temp);
  314.       }
  315.     }
  316.  
  317.     //  Calculate pawnstructurevalue
  318.     RootValue = pawnstrval(-1, Player) - pawnstrval(-1, Opponent);
  319.  
  320.     //  Calculate static value for pawn structure
  321.     for (color = white; color <= black; ((int)color)++) {
  322.       oppcolor = (COLORTYPE)(1 - color);
  323.       pawnfiletab = leftsidetab = rightsidetab = behindoppass = 0;
  324.       oppasstab = 0xff;
  325.       for (rank = 1; rank < 7; rank++) {
  326.         //  Squares where opponents pawns are passed pawns
  327.         oppasstab &= SETOFFILE((~(pawnfiletab | leftsidetab | rightsidetab)));
  328.         //  Squares behind the opponents passed pawns
  329.         behindoppass |= (oppasstab & pawntab[oppcolor][7 - rank]);
  330.         //  squares which are covered by a pawn
  331.         leftchaintab = leftsidetab;
  332.         rightchaintab = rightsidetab;
  333.         pawnfiletab = pawntab[color][rank]; //  squares w/ pawns
  334.         //  squares w/ a pawn beside them
  335.         leftsidetab = SETOFFILE((pawnfiletab << 1) & 0xff);
  336.         rightsidetab = SETOFFILE((pawnfiletab >> 1) & 0xff);
  337.         sidetab = leftsidetab | rightsidetab;
  338.         chaintab = leftchaintab | rightchaintab;
  339.         //  squares covering a pawn
  340.         temp = pawntab[color][rank+1];
  341.         leftcovertab = SETOFFILE((temp << 1) & 0xff);
  342.         rightcovertab = SETOFFILE((temp >> 1 ) & 0xff);
  343.         sq = rank << 4;
  344.         if (color == black)
  345.           sq ^= 0x70;
  346.         bit = 1;
  347.         while (bit) {
  348.           strval = 0;
  349.           if (bit & sidetab)
  350.             strval = SIDEPAWN;
  351.           else if (bit & chaintab)
  352.             strval = CHAINPAWN;
  353.           if (bit & leftcovertab)
  354.             strval += COVERPAWN;
  355.           if (bit & rightcovertab)
  356.             strval += COVERPAWN;
  357.           if (bit & pawnfiletab)
  358.             strval += NOTMOVEPAWN;
  359.           PVTable[color][pawn][sq] += strval;
  360.           if ((materiallevel <= 0) || (oppcolor != ProgramColor))
  361.           {
  362.             if (bit & oppasstab)
  363.              PVTable[oppcolor][pawn][sq] += passpawnrank[7 - rank];
  364.             if (bit & behindoppass)
  365.             {
  366.              temp = sq ^ 0x10;
  367.              for (tempcolor = black; tempcolor >= white
  368.                ; ((int)tempcolor)--)
  369.              {
  370.                PVTable[tempcolor][rook][sq] +=
  371.                  ROOKBEHINDPASSPAWN;
  372.                if (rank == 6)
  373.                  PVTable[tempcolor][rook][temp] +=
  374.                   ROOKBEHINDPASSPAWN;
  375.              }
  376.             }
  377.           }
  378.           sq++;
  379.           bit = SETOFFILE((bit << 1) & 0xff);
  380.         }
  381.       }
  382.     }
  383.  
  384.   //  Calculate penalty for blocking center pawns with a bishop
  385.   for (sq = 3; sq < 5; sq ++) {
  386.     if (Board[sq + 0x10].piece == pawn && Board[sq + 0x10].color == white)
  387.       PVTable[white][bishop][sq + 0x20] -= BISHOPBLOCKVALUE;
  388.     if (Board[sq+0x60].piece == pawn && Board[sq+0x60].color == black)
  389.       PVTable[black][bishop][sq+0x50] -= BISHOPBLOCKVALUE;
  390.   }
  391.   for (square = 0x77; square >= 0; square--) //  Calculate RootValue
  392.     if (!(square & 0x88))
  393.       if (Board[square].piece != empty)
  394.         if (Board[square].color == Player)
  395.           RootValue += PiecePosVal(Board[square].piece, Player, square);
  396.         else
  397.           RootValue -= PiecePosVal(Board[square].piece, Opponent, square);
  398. }
  399.  
  400. //----------------------------------------------------------------------------
  401.  
  402. int value;
  403. SQUARETYPE castsquare, cornersquare, epsquare;
  404.  
  405. //
  406. //  Update pawnbit and calculates value when a pawn is removed from line
  407. //
  408. inline int
  409. decpawnstrval(COLORTYPE color, FILETYPE line)
  410. {
  411.   temp = ~filebittab[line];
  412.   pawnbit[Depth][color].one = SETOFFILE((pawnbit[Depth][color].one & temp) |
  413.       pawnbit[Depth][color].dob);
  414.   pawnbit[Depth][color].dob &= SETOFFILE(temp);
  415.   return int(pawnstrval(Depth, color) - pawnstrval(DEPTHTYPE(Depth - 1), color));
  416. }
  417.  
  418. //
  419. //  Update pawnbit and calculates value when a pawn moves
  420. //  from old to new1 file
  421. //
  422. static int
  423. movepawnstrval(COLORTYPE color, FILETYPE new1, FILETYPE old)
  424. {
  425.   temp = filebittab[new1];
  426.   temp2 = ~filebittab[old];
  427.   pawnbit[Depth][color].dob |= SETOFFILE((pawnbit[Depth][color].one & temp));
  428.   pawnbit[Depth][color].one = SETOFFILE((pawnbit[Depth][color].one & temp2) |
  429.                               pawnbit[Depth][color].dob | temp);
  430.   pawnbit[Depth][color].dob &= SETOFFILE(temp2);
  431.   return int(pawnstrval(Depth, color) - pawnstrval(DEPTHTYPE(Depth - 1), color));
  432. }
  433.  
  434. //----------------------------------------------------------------------------
  435.  
  436. //
  437. //  Calculate STATIC evaluation of the move
  438. //
  439. int
  440. StatEvalu(MOVETYPE *move)
  441. {
  442.   value = 0;
  443.   if (move->spe)
  444.     if (move->movpiece == king) {
  445.       GenCastSquare(move->new1, &castsquare, &cornersquare);
  446.       value = PiecePosVal(rook, Player, castsquare) -
  447.           PiecePosVal(rook,Player, cornersquare);
  448.       if (move->new1 > move->old)
  449.         value += castvalue[shrt-1];
  450.       else
  451.         value += castvalue[lng-1];
  452.  
  453.     } else if (move->movpiece == pawn) {
  454.       epsquare = move->new1 - PawnDir[Player];  //  E.p. capture
  455.       value = PiecePosVal(pawn, Opponent, epsquare);
  456.  
  457.     } else      //  Pawnpromotion
  458.       value = PiecePosVal(move->movpiece, Player, move->old) -
  459.           PiecePosVal(pawn, Player, move->old) +
  460.           decpawnstrval(Player, FILETYPE(move->old & 7));
  461.  
  462.     if (move->content != empty) {  //  normal moves
  463.       value += PiecePosVal(move->content, Opponent, move->new1);
  464.       //  Penalty for exchanging pieces when behind in material
  465.       if (abs(MainEvalu) >= 0x100)
  466.         if (move->content != pawn)
  467.           if ((ProgramColor == Opponent) == (MainEvalu >= 0))
  468.             value -= EXCHANGEVALUE;
  469.     }
  470.     pawnbit[Depth][black] = pawnbit[Depth - 1][black];  //  calculate pawnbit
  471.     pawnbit[Depth][white] = pawnbit[Depth - 1][white];
  472.     if (move->movpiece == pawn && (move->content != empty || move->spe))
  473.       value += movepawnstrval(Player, FILETYPE(move->new1 & 7), FILETYPE(move->old & 7));
  474.     if (move->content == pawn || move->spe && move->movpiece == pawn)
  475.       value -= decpawnstrval(Opponent, FILETYPE(move->new1 & 7));
  476.     //  Calculate value of move
  477.     return value + PiecePosVal(move->movpiece, Player, move->new1) -
  478.         PiecePosVal(move->movpiece, Player, move->old);
  479. }
  480.